home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 21 / Cream of the Crop 21 (Terry Blount) (October 1996).iso / editor / auror300.zip / EXT.AML < prev    next >
Text File  |  1996-07-17  |  74KB  |  2,985 lines

  1. //--------------------------------------------------------------------
  2. // The Aurora Editor v3.0, Copyright (C) 1993-1996 nuText Systems
  3. //
  4. // EXT.AML
  5. // Library Extensions (included by Main.aml)
  6. //
  7. // You should be very familiar with the macro language before making
  8. // changes to this file. If you have made any changes, save this file
  9. // and select Recompile the Editor from the Set menu. Exit and
  10. // re-enter the editor for your changes to take effect.
  11. //--------------------------------------------------------------------
  12.  
  13. //--------------------------------------------------------------------
  14. // All windows
  15. //--------------------------------------------------------------------
  16.  
  17. object a
  18.  
  19.   // get the drive and path portion of a filespec
  20.   function getpath (file)
  21.     file [1..pos "\\" file 'r']
  22.   end
  23.  
  24.   // get the name and extension portion of a filespec
  25.   function getname (file)
  26.     file [(pos "\\" file 'r') + 1..TO_END]
  27.   end
  28.  
  29.   // get the extension portion of a filespec
  30.   function getext (file)
  31.     p = pos '.' file 'r'
  32.     if? p file [p..TO_END] ''
  33.   end
  34.  
  35.   // append a default extension for filenames that don't have one
  36.   function defext (file extension)
  37.     if pos '.' file then
  38.       file
  39.     else
  40.       file + '.' + extension
  41.     end
  42.   end
  43.  
  44.   // force a filename to have an extension
  45.   function forceext (file ext)
  46.     p = pos '.' file 'r'
  47.     return (if? p  file [1..p]  file + '.') + ext
  48.   end
  49.  
  50.   // generate shiftkey events from raw <shiftkey> event
  51.   event <shiftkey> (newstate oldstate)
  52.     send ( if newstate & 3 and not (oldstate & 3) then
  53.              "shiftdown"
  54.            elseif oldstate & 3 and not (newstate & 3) then
  55.              "shiftup"
  56.            elseif newstate & 10h and not (oldstate & 10h) then
  57.              "scrlockdown"
  58.            elseif oldstate & 10h and not (newstate & 10h) then
  59.              "scrlockup"
  60.            end )
  61.     pass
  62.   end
  63.  
  64.   // generate multi-key events
  65.   function prefix (keycode)
  66.     keyname = locase (geteventname keycode)
  67.     say  keyname + "<more...>"
  68.     keyname2 = locase (geteventname (getkey))
  69.     queue  keyname + keyname2
  70.     // allow the <ctrl> key to be held down...
  71.     if keyname [1..5] == "<ctrl" and keyname2 [1..5] == "<ctrl" then
  72.       queue keyname + '<' + keyname2 [7 : TO_END]
  73.     end
  74.     display
  75.   end
  76.  
  77.   // repeat keys for a user-specified number of times
  78.   function askrepkey
  79.     say "Enter keys to repeat, then <esc>:"
  80.     hidecursor
  81.     keycode = getkey
  82.     while keycode <> <esc> do
  83.       keystring = keystring + (char2 keycode)
  84.       keycode = getkey
  85.     end
  86.     if keystring then
  87.       strlen = length keystring
  88.       loop (ask "Number of repetitions") times
  89.         j = 1
  90.         while j < strlen do
  91.           queuekey (bin2int keystring [j : 2])
  92.           j = j + 2
  93.         end
  94.         repeat
  95.           dispatch
  96.         until not event?
  97.       end
  98.     end
  99.   end
  100.  
  101.   // write to the screen background
  102.   function writebak (string attr x y)
  103.     w = getcurrwin
  104.     while w do
  105.       hidewindow w
  106.       w = getprevwin w
  107.     end
  108.     gotoscreen
  109.     writestr string attr x y
  110.   end
  111.  
  112.   // file prompt with picklist
  113.   function askfile (pstring pstring2)
  114.     file = ask pstring "_load"
  115.     if file == ' ' then
  116.       file = "*.*"
  117.     end
  118.     if (dir? file) or (directory? file) then
  119.       filespec = qualify file (getbufname)
  120.       file = pickfile filespec (onname filespec 't') pstring2
  121.     end
  122.     return file
  123.   end
  124.  
  125.   // execute a fully qualified Dos program
  126.   // (saving and restoring the current path)
  127.   private function os (program options)
  128.     cp = getcurrpath
  129.     currpath (getpath (getbufname))
  130.     r = system program options
  131.     currpath cp
  132.     return r
  133.   end
  134.  
  135.   // shell to Dos by executing Command.com
  136.   function shell
  137.     os (getenv "COMSPEC") "ch"
  138.   end
  139.  
  140.   // execute Dos commands, programs, and .bat files
  141.   function run (file options)
  142.     if file then
  143.       os (getenv "COMSPEC") + " /c " + file  options
  144.     else
  145.       shell
  146.     end
  147.   end
  148.  
  149.   // execute Dos commands or programs and capture the output
  150.   // via Dos redirection (will not capture .bat file output)
  151.   function runcap (command options)
  152.     _cap = _cap + 1
  153.     capfile = qualify  "capture." + _cap  (getbufname)
  154.     run  command + '>' + capfile  options
  155.     open capfile
  156.     deletefile capfile
  157.   end
  158.  
  159.   // translate an AML compiler error code to an error message
  160.   function errormsg (error)
  161.     runmacro (bootpath "macro\\erroraml.x") '' error
  162.   end
  163.  
  164.   // compile a macro with error messages
  165.   // the cursor is moved to any syntax errors
  166.   function compilemacro2 (source dest msg)
  167.     if not source then
  168.       source = getbufname
  169.     end
  170.     if msg then
  171.       say msg
  172.     end
  173.     source = qualify (defext source "aml") (getbufname)
  174.     error = compilemacro source (if? dest dest (forceext source 'x'))
  175.  
  176.     if error then
  177.  
  178.       // get additional error info
  179.       column = geterror 'k'
  180.       line = geterror 'l'
  181.       file = geterror 'f'
  182.  
  183.       // translate error code to an error message
  184.       msg = errormsg error
  185.       if not msg then
  186.         msg = "Error " + error
  187.       end
  188.  
  189.       // position the cursor to the error
  190.       if error <> 1001 and (open file) then
  191.         gotopos column line
  192.         send "onfound"
  193.       end
  194.  
  195.       // display the error
  196.       location = file + " (line " + line + ", col " + column + "): "
  197.       // 1 or 2 line msgbox
  198.       msgbox location +
  199.              (if? (length location + length msg) > getvidcols - 8 "\n") +
  200.              msg  "Error!" 'b'
  201.     else
  202.       if wintype? "edit_fmgr" then
  203.         say "Done."
  204.       end
  205.     end
  206.  
  207.     return error
  208.   end
  209.  
  210.   // regenerate the editor boot macro (A.x)
  211.   function regen (msg)
  212.     dest = bootpath "main.x"
  213.     error = compilemacro2 (bootpath "main.aml") dest msg
  214.     if not error then
  215.       bootfile = bootpath "a.x"
  216.       deletefile bootfile
  217.       renamefile dest bootfile
  218.     end
  219.     return error
  220.   end
  221.  
  222.   // regenerate the editor boot macro (a.x) with a message
  223.   function recompile
  224.     if not regen then
  225.       msgbox "Exit and re-enter for changes to take effect. "
  226.     end
  227.   end
  228.  
  229.   // macro picklist
  230.   function pickmacro
  231.     runmacro2 (pickfile getbootpath + "macro\\*.x" "Select a macro to run"
  232.                         '' "maclist")
  233.   end
  234.  
  235.   // execute a compiled macro file w/error msg - force .x extension
  236.   // (run in the Macro\ subdirectory, if no path is specified)
  237.   function runmacro2 (macrofile)
  238.     if macrofile then
  239.       if macrofile == ' ' then
  240.         pickmacro
  241.       else
  242.         runmacro (qualify (forceext (if? macrofile macrofile (getbufname)) 'X')
  243.                    getbootpath + "macro\\")
  244.         if geterror then
  245.           msgbox (errormsg (geterror))
  246.         end
  247.       end
  248.     end
  249.   end
  250.  
  251.   function helpmacro (macro)
  252.     runmacro (bootpath "macro\\helpmac.x") '' macro
  253.   end
  254.  
  255.   // run a configuration macro
  256.   function runcfg (macrosuffix)
  257.     runmacro getbootpath + "cfg\\cfg" + macrosuffix + ".x"
  258.   end
  259.  
  260.   // save current configuration to Config.aml and Color.aml and recompile
  261.   function savecfg runcfg "upd"
  262.  
  263.   // send a string to the default printer device
  264.   function printstr (string)
  265.     if string then
  266.       if (openfile _PrtDev 'w') <> -1 then
  267.         writefile string
  268.         closefile
  269.       end
  270.     end
  271.   end
  272.  
  273.   // open a new file
  274.   function opennew (file options)
  275.     prevbufname = getbufname
  276.     buffer = createbuf
  277.     if buffer then
  278.       setbufname (qualify (if? file file "new.txt") prevbufname)
  279.       openbuf buffer options
  280.     end
  281.   end
  282.  
  283.   // toggle the video mode between 80x25 and 80x50
  284.   function togglemode
  285.     videomode 80 (if? getvidrows == 25  50 25)
  286.   end
  287.  
  288.   // search/replace with verification
  289.   // (returns the number of replacements made)
  290.   function replver (searchstr replstr options)
  291.  
  292.     variable title
  293.  
  294.     repeat
  295.       len = find searchstr options
  296.       if len then
  297.  
  298.         if not title then
  299.           title = gettitle
  300.           settitle  "Replace (Yes/No/All/One/Reverse/Undo/Quit)? "
  301.           // remove global for next find
  302.           options = sub 'g' '' options
  303.         end
  304.  
  305.         send "onfound" len
  306.  
  307.         // get keycode and convert to lower case
  308.         p = getkey | 020h
  309.         case p
  310.  
  311.           when <y>, <o>, <a>
  312.             undobegin
  313.             l = (replace searchstr replstr  (sub 'r' '' options) + "*") - 1
  314.             if not (pos 'r' options) then
  315.               right l
  316.               if (pos 'x' options) and (getcol == getlinelen) then
  317.                 right
  318.               end
  319.             end
  320.             count = count + 1
  321.             if p <> <y> then
  322.               len = ''
  323.               if p == <a> then
  324.                 count = count + (replace searchstr replstr  options + "a")
  325.               end
  326.             end
  327.             undoend
  328.  
  329.           when <u>
  330.             if count then
  331.               undo
  332.               count = count - 1
  333.               if pos 'r' options then
  334.                 right 1
  335.               else
  336.                 if getcol == 1 then
  337.                   if up then
  338.                     col MAX_COL
  339.                   end
  340.                 else
  341.                   left l
  342.                 end
  343.               end
  344.             end
  345.  
  346.           when <n>
  347.              // do nothing
  348.  
  349.           when <r>
  350.              options = if? (pos 'r' options) (sub 'r' '' options)  options + 'r'
  351.  
  352.           otherwise
  353.             if not count then
  354.               count = '0'
  355.             end
  356.             break
  357.         end
  358.       end
  359.     until not len
  360.  
  361.     if title then
  362.       settitle title
  363.     end
  364.  
  365.     return count
  366.   end
  367.  
  368.  
  369.   // search for a multi-string search argument
  370.   function search (searchstr reverse rep refopt refrepl)
  371.  
  372.     variable replstr, options
  373.  
  374.     // split up search multi-string
  375.     if pos '/' searchstr then
  376.       n = splitstr '' searchstr  ref searchstr  ref replstr  ref options
  377.       if n > 1 then
  378.         if n == 2 then
  379.           options = replstr
  380.           replstr = ''
  381.           // case sensitive
  382.           if not options then
  383.             options = 'c'
  384.           end
  385.         end
  386.       end
  387.     end
  388.  
  389.     if searchstr then
  390.  
  391.       // default options
  392.       if not options then
  393.         options = _SearchOpt
  394.         if n > 2 then
  395.           options = options + _ReplaceOpt
  396.         end
  397.       end
  398.  
  399.       // reverse search direction if specified
  400.       if reverse then
  401.         options = if pos 'r' options then
  402.                     sub 'r' '' options
  403.                   else
  404.                     options + 'r'
  405.                   end
  406.       end
  407.  
  408.       // remove global for repeat find
  409.       if rep and (pos 'g' options) then
  410.         options = sub 'g' '' options
  411.       end
  412.  
  413.       // return values for calling function to check
  414.       refopt  = options
  415.       refrepl = n >= 3
  416.  
  417.       // resurface marked window for block search
  418.       if pos 'b' options then
  419.         buffer = getmarkbuf
  420.         if buffer and buffer <> getcurrbuf then
  421.           currwin (getcurswin (getcurrcurs buffer))
  422.         end
  423.       end
  424.  
  425.       // search and replace
  426.       if n >= 3 then
  427.  
  428.         // do the replace
  429.         if pos 'a' options then
  430.           replace searchstr replstr options
  431.         else
  432.           replver searchstr replstr options
  433.         end
  434.  
  435.       // search only
  436.       else
  437.         find searchstr options
  438.       end
  439.     end
  440.   end
  441.  
  442.   // hot key for the file mgr and file picklists
  443.   function onhotkey (character)
  444.     if _oL == getrow then
  445.       // backspace
  446.       if character == '\x08' then
  447.         popcursor
  448.         _oS = if? (length _oS > 1) _oS [1..length _oS - 1] ''
  449.       else
  450.         _oS = _oS + character
  451.         pushcursor
  452.       end
  453.     else
  454.       if character == '\\' then
  455.         character = '\x00'
  456.       end
  457.       _oS = character
  458.       pushcursor
  459.     end
  460.     searchstr = '^ *' + _oS
  461.     if bufferflag '?d' then
  462.       if getbinarylen then
  463.         startcol = 17
  464.       else
  465.         find "\xff\x00" '[lgr'
  466.         startcol = getcol
  467.         searchstr [2] = '\xff'
  468.       end
  469.     else
  470.       startcol = 1
  471.     end
  472.     markcolumn startcol MAX_COL 1 (getlines) 'T'
  473.     len = (find searchstr 'bxi*' 'T') or (find searchstr 'bxig' 'T')
  474.     destroymark 'T'
  475.     if len then
  476.       if getrow > getviewbot or getrow < getviewtop then
  477.         adjustrow getviewrows / 3
  478.       end
  479.       if _oS then
  480.         display
  481.         hilite len 1 (getpalette (if? (wintype? "fmgr") 33 18)) (getcol)
  482.       end
  483.       _oL = getrow
  484.     else
  485.       popcursor 'ad'
  486.       _oL = ''
  487.       if length _oS > 1 then
  488.         onhotkey character
  489.       // not found
  490.       else
  491.         beep 320 70
  492.       end
  493.     end
  494.   end
  495.  
  496.   // generic prompt for a string
  497.   function ask (prompt history init title options width)
  498.  
  499.     variable value
  500.  
  501.     if not options then
  502.       options = _PromptStyle
  503.       suffix = if? (pos '2' options) ':' '>'
  504.     end
  505.  
  506.     // highlight cursor position
  507.     if wintype? "edit" then
  508.       hilite 1 1 (getpalette (if? (inmark?) 9 8))
  509.     end
  510.  
  511.     // dialog box prompt
  512.     if pos 'd' options then
  513.       if suffix then
  514.         prompt = prompt + ':'
  515.       end
  516.       if not width then
  517.         width = 48
  518.       end
  519.  
  520.       dialog (if? title title "Prompt")  18 + width  5 'cp'
  521.       field  prompt 3 2 width - (if? prompt [0] == '>' (length prompt - 3) -2) init history
  522.       button "O&k"    width + 8 2 8
  523.       button "Cancel" width + 8 4 8
  524.  
  525.       if (getdialog ref value) == 'Ok' then
  526.         return (if? value value ' ')
  527.       end
  528.     else
  529.       // other prompt styles
  530.       if (case options
  531.             when 'c' askline ref value prompt + suffix       history init
  532.             when '1' askbox1 ref value prompt + suffix + ' ' history init
  533.             when '2' askbox  ref value prompt + suffix       history init
  534.           end) then
  535.         return (if? value value ' ')
  536.       end
  537.     end
  538.   end
  539.  
  540.   // replace/append/cancel or ok/cancel menus
  541.   function askrac (file menuname)
  542.     if _ConRpl == 'y' and (locatefile file) then
  543.       locase (popup (if? menuname menuname "rac" )
  544.                       (onname file) + " Exists" +
  545.                       (if? menuname == "ok" ". Replace?")) [1]
  546.     else
  547.       'r'
  548.     end
  549.   end
  550.  
  551.   // print the current buffer or mark
  552.   function print (options)
  553.     header = _PrtHdr
  554.     printformat '' _PrtOpt _PrtPag _PrtLeft _PrtTop _PrtRight _PrtBot
  555.                    _PrtSpace _PrtCop
  556.     if not (posnot ' ' header) or (dir? (getbufname)) then
  557.       date = getdate
  558.       header = getbufname + "   (" + date [posnot ' ' date : TO_END] +
  559.                                ' ' + gettime + ')'
  560.     end
  561.     if not ( if pos 'b' options  then printblock _PrtDev header '' _PrtIni
  562.               else    printbuf _PrtDev header '' _PrtIni end ) then
  563.       say "Print failed" 'b'
  564.     end
  565.   end
  566.  
  567.   // print a file or directory with the current printer settings
  568.   function printfile (file)
  569.     if loadbuf (if? file [LAST_CHAR] == '\\' file + "*.*" file)
  570.                '' '' _FmgrOpt _TruncLength then
  571.       if not break? then
  572.         print
  573.         destroybuf
  574.         return TRUE
  575.       end
  576.     end
  577.   end
  578.  
  579.   // backup a file and return the backup filename if sucessful
  580.   function backup (file)
  581.     if locatefile file then
  582.       dir = _BackupDir
  583.       if dir then
  584.         if length dir > 3 and dir [LAST_CHAR] == "\\" then
  585.           dir = dir [1..length dir - 1]
  586.         end
  587.         createdir dir
  588.         dir = qualify dir
  589.         backup_file = if pos "*.*" dir then
  590.                         qualify (getname file) dir
  591.                       else
  592.                         msgbox "Unable to create backup file!"
  593.                                "Warning!"
  594.                         return 1
  595.                       end
  596.       else
  597.         backup_file = forceext file _BackupExt
  598.       end
  599.  
  600.       if not icompare file backup_file then
  601.         // delete the old backup file
  602.         deletefile backup_file
  603.  
  604.         // attempt a rename
  605.         if not renamefile file backup_file then
  606.           // try copy if rename fails
  607.           if (copyfile file backup_file) <= 0 then
  608.             msgbox "File backup failed!" "Error"
  609.             return 0
  610.           end
  611.         end
  612.       end
  613.       return backup_file
  614.     else
  615.       return 1
  616.     end
  617.   end
  618.  
  619.   // save the current file to disk
  620.   function save (file options)
  621.     variable c1, c2
  622.  
  623.     // check for a truncated file
  624.     if (bufferflag 't?') and
  625.        not (icompare (popup "ok" "Truncated file - are you sure?") "Ok") then
  626.       return
  627.     end
  628.  
  629.     file = if file then
  630.              qualify file (getbufname)
  631.            else
  632.              getbufname
  633.            end
  634.     // check for read/only
  635.     if (bufferflag 'r?') or (fileattr? file 'r') then
  636.       say "Read Only!" 'b'
  637.     else
  638.       backup_file = 1
  639.       if send "setting?" 'B' then
  640.         backup_file = backup file
  641.       end
  642.       if not backup_file then
  643.         say "Backup failed" 'b'
  644.       else
  645.         send "onsave" file
  646.  
  647.         // get fold comments for the file (if any)
  648.         send "oncomment" file ref c1 ref c2
  649.         options = _SaveOpt + options
  650.         if not savebuf file
  651.                  (if? (pos 'e' options) 'e' + _TabWidth) + options  ''
  652.                  (if not getbinarylen then hex2bin _LineDlm end) ''
  653.                  (if? c1 c1 + _FoldSign) c2 then
  654.  
  655.           // restore the backup after save failure
  656.           if backup_file <> 1 then
  657.             if not renamefile backup_file file then
  658.               copyfile backup_file file
  659.             end
  660.           end
  661.           msgbox "Save failed!  Check file path / file attributes / disk space"  "Error!" 'b'
  662.           return 0
  663.         else
  664.           1
  665.         end
  666.       end
  667.     end
  668.   end
  669.  
  670.   // save-as prompt
  671.   function asksaveas (options name dext)
  672.     file = ask "Save " + (onname (if? name name (getname (getbufname)))) +
  673.                " as"  "_load"
  674.     if file then
  675.       file = qualify file (getbufname)
  676.       if dext then
  677.         file = defext file dext
  678.       end
  679.       addhistory "_load" file
  680.       action = locase (askrac file)
  681.       if pos action "ra" then
  682.         save file options + (if? action == 'a' 'a')
  683.       end
  684.     end
  685.   end
  686.  
  687.   // generic prompt with command execution
  688.   function askx (pstring history func parm2)
  689.     parm1 = ask pstring history
  690.     if parm1 then
  691.       send func parm1 parm2
  692.       if history then
  693.         addhistory history parm1
  694.       end
  695.       return 1
  696.     end
  697.   end
  698.  
  699.   // open prompt
  700.   function askopen
  701.     file = ask "[file/ibcenz] Open" "_load"
  702.     if file then
  703.       // addhistory not needed for open
  704.       open file
  705.     end
  706.   end
  707.  
  708.   // open binary prompt
  709.   function askopenb
  710.     file = askfile "File to open in Binary Mode" "Open Binary"
  711.     if file then
  712.       open file 'b'
  713.     end
  714.   end
  715.  
  716.   // macro expression prompt
  717.   function askeval
  718.     if askx "Macro Expression" "_cmd" "eval" then
  719.       error = geterror 'c'
  720.       if error then
  721.         msgbox "Expression column " + (geterror 'k') +
  722.                ": " + (errormsg error)  "Error" 'b'
  723.       end
  724.     end
  725.   end
  726.  
  727.  
  728. object mon
  729.  
  730.   // erase key macros
  731.   function erasekey2 (options)
  732.     if erasekey options then
  733.       _kd = TRUE
  734.       display
  735.       say (if? (pos options 'a') "All keys macros erased"
  736.                                  "Scrap key macro erased")
  737.     end
  738.   end
  739.  
  740.   // toggle the key macro record mode
  741.   function record
  742.     if not playing? then
  743.       _kd = TRUE
  744.       if not setting? 'R' then
  745.         erasekey
  746.         record_on = TRUE
  747.       end
  748.       setting 'R' TOGGLE
  749.       say "Record" + (if? record_on "ing..." " Off")
  750.     end
  751.   end
  752.  
  753.   // play a key macro
  754.   function play (keymacro)
  755.     setdisplay OFF
  756.     if not (playkey keymacro) then
  757.       say "No key macro to play." 'b'
  758.     end
  759.     setdisplay ON
  760.   end
  761.  
  762.  
  763. //--------------------------------------------------------------------
  764. // Edit windows and File Manager windows
  765. //--------------------------------------------------------------------
  766.  
  767. object edit_fmgr
  768.  
  769.   // close all windows
  770.   function closeall (options)
  771.     a.__G = ON
  772.     begdesk
  773.     while getwincount and (send "close" options) end
  774.     enddesk
  775.     a.__G = OFF
  776.   end
  777.  
  778.   // move the cursor to top or bottom of a mark
  779.   function gotomark (options)
  780.     if mark? then
  781.       window = getcurswin (getcurrcurs (getmarkbuf))
  782.       if window then
  783.         currwin window
  784.       end
  785.       // (use 'down' since it adjusts for real tabs)
  786.       down (if? (pos 'b' options) (getmarkbot) (getmarktop)) - getrow
  787.       if window then
  788.         send "onfound"
  789.       end
  790.     else
  791.       say "Block not found" 'b'
  792.     end
  793.   end
  794.  
  795.   // goto a bookmark with message
  796.   function gotobook2 (bookmark)
  797.     msg = "Bookmark " + (if? bookmark bookmark)
  798.     bookbuf = getbookbuf bookmark
  799.     if bookbuf <> getwinbuf then
  800.       open (getbufname bookbuf)
  801.     end
  802.     if gotobook bookmark then
  803.       display
  804.       say msg
  805.     else
  806.       say msg + " not found"  'b'
  807.     end
  808.   end
  809.  
  810.   // prompt to goto a bookmark
  811.   function askbook (msg)
  812.     askx (if? msg msg "Bookmark Name") "_book" "gotobook2"
  813.   end
  814.  
  815.   // cycle though all existing bookmarks
  816.   function cyclebook
  817.     l = _lb
  818.     bookmark = if? l (getprevbook l) (getcurrbook)
  819.     if not bookmark then
  820.       buffer = getcurrbuf
  821.       while buffer do
  822.         if getcurrbook buffer then
  823.           bookmark = getcurrbook buffer
  824.         end
  825.         buffer = getprevbuf buffer
  826.       end
  827.     end
  828.     _lb = bookmark
  829.     gotobook2 bookmark
  830.   end
  831.  
  832.   // generic prompt to change a configuration variable
  833.   private function askc (pstring configvar history)
  834.     newvalue = ask pstring history prf [configvar]
  835.     if newvalue then
  836.       prf [configvar] = newvalue
  837.     end
  838.   end
  839.  
  840.   // prompts to change specific configuration variables
  841.   function askclip    askc "Clipboard Name" "ClipName"
  842.   function askprthdr  askc "Current Header/Footer" "PrtHdr"
  843.  
  844.   // prompt to run a macro
  845.   function askrmacro  askx "Run Macro File"  "_load" "runmacro2"
  846.  
  847.   // prompt to compile a macro
  848.   function askcmacro  askx "Compile Macro File"  "_load" "compilemacro2"
  849.  
  850.   // Dos command prompt
  851.   function askrun     askx "Dos Command" "_os" "run" "ck"
  852.  
  853.   // prompt to capture Dos output
  854.   function askruncap  askx "Capture Dos Output" "_os" "runcap" 'c'
  855.  
  856.   // open key macro file with messages
  857.   function openkey2 (file)
  858.     if openkey file then
  859.       say (getname file) + " loaded"
  860.     else
  861.       say "Load failed" 'b'
  862.     end
  863.   end
  864.  
  865.   // prompt to open a key macro file
  866.   function askopenkey
  867.     file = ask "Key macro filename" "_load"
  868.     if file then
  869.       openkey2 (qualify (defext file "mac") (getbufname))
  870.     end
  871.   end
  872.  
  873.   // prompt to save current key macros
  874.   function asksavekey
  875.     file = ask "Save current key macros as" "_load"
  876.     if file then
  877.       file = qualify (defext file "mac") (getbufname)
  878.       if pos (askrac file "ok") "or" 'i' then
  879.         if not savekey file then
  880.           say "Save failed" 'b'
  881.         end
  882.       end
  883.     end
  884.   end
  885.  
  886.   // prompt to scan files for a string
  887.   function askscan (list)
  888.     runmacro (bootpath "macro\\scan.x") '' (if? list (getcurrbuf))
  889.   end
  890.  
  891.   // reload the current file from disk
  892.   function reopen (file)
  893.     open (if? file file (getbufname)) 'r'
  894.   end
  895.  
  896.   // open last file or directory
  897.   function openlast
  898.     file = gethiststr "_load"
  899.     if file then
  900.       open file
  901.     end
  902.   end
  903.  
  904.   // open an AML configuration file in boot directory
  905.   function opencfg (file)
  906.     open (bootpath  file + ".aml")
  907.   end
  908.  
  909.   // quick reference help
  910.   function quickref (options openopt)
  911.     quickfile = getbootpath + (if? options <> 'o' "doc\\") +
  912.                   case options [1]
  913.                     when 'l'  "language.dox"
  914.                     when 'f'  "function.dox"
  915.                     when 'q'  "quickfun.dox"
  916.                     when 'o'  "orderfrm.doc"
  917.                     when 't'  "tips.dox"
  918.                     otherwise "user.dox"
  919.                   end
  920.  
  921.     if (wintype? "edit") and (pos 'w' options) then
  922.       wordstr = send "getword" "a-zA-Z0-9?<>"
  923.     end
  924.  
  925.     if file? quickfile then
  926.  
  927.       open quickfile openopt
  928.  
  929.       // make read/only
  930.       if options [1] <> 'o' then
  931.         bufferflag '+r'
  932.       end
  933.  
  934.       if wordstr then
  935.         gotopos 1 1
  936.  
  937.         // find string in reference
  938.         if find '\xff' + wordstr + '\xff' then
  939.           right
  940.           send "onfound"  length wordstr
  941.  
  942.         // not found? then try function header in Ext.aml
  943.         elseif poschar 'fq' options then
  944.           close
  945.           ext = bootpath "ext.aml"
  946.           closeit = _MultCopy == 'n' and not (findbuf ext)
  947.           open ext openopt
  948.           gotopos 1 1
  949.           n = find "function #" + wordstr  'xw'
  950.           if n then
  951.             send "onfound" n
  952.  
  953.           else
  954.             // still not found? then go back to the reference
  955.             if closeit then
  956.               close
  957.             end
  958.             open quickfile openopt
  959.             // make read/only
  960.             bufferflag '+r'
  961.           end
  962.         end
  963.       end
  964.     else
  965.       msgbox quickfile + " not found."
  966.     end
  967.   end
  968.  
  969.  
  970. //--------------------------------------------------------------------
  971. // Prompts and Edit windows
  972. //--------------------------------------------------------------------
  973.  
  974. object prompt
  975.  
  976.   // support for cua-style <shift> key marking
  977.   function smark
  978.     if shiftkey? then
  979.       if _shfx then
  980.         undobegin
  981.         destroymark
  982.         markstream _shfx _shfx _shfy _shfy
  983.         _shfx = ''
  984.         _shfy = ''
  985.       end
  986.       extendmark
  987.     end
  988.   end
  989.  
  990.   // set anchor for shift-key marking
  991.   function shiftdown
  992.     _shfx = getcol
  993.     _shfy = getrow
  994.     pass
  995.   end
  996.  
  997.   // end shift-key mark
  998.   function shiftup
  999.     if not _shfx then
  1000.       stopmark
  1001.       undoend
  1002.     end
  1003.     pass
  1004.   end
  1005.  
  1006.   // backspace in a prompt
  1007.   function backsp
  1008.     if getcol > 1 then
  1009.       left
  1010.       delchar
  1011.     end
  1012.   end
  1013.  
  1014.   // get the word at the cursor
  1015.   function getword (charset column mark)
  1016.     variable a
  1017.     if not column then
  1018.       column = getcol
  1019.     end
  1020.     if column <= getlinelen then
  1021.       if not charset then
  1022.         charset = _CSet
  1023.       end
  1024.       b = posnot charset (gettext column)
  1025.       if b <> 1 then
  1026.         b = if? b  column + b - 2  getlinelen
  1027.         a = posnot charset (gettext 1 column) 'r'
  1028.         a = if? a  a + 1  1
  1029.         if mark then
  1030.           undobegin
  1031.           destroymark
  1032.           markchar a b
  1033.           undoend
  1034.         else
  1035.           gettext a  b - a + 1
  1036.         end
  1037.       end
  1038.     end
  1039.   end
  1040.  
  1041.   // mark the word at the cursor using getword
  1042.   function markword (charset)
  1043.     getword charset '' 1
  1044.   end
  1045.  
  1046.   // mark to end-of-line
  1047.   function markeol
  1048.     undobegin
  1049.     destroymark
  1050.     if getcol <= getlinelen then
  1051.       markchar '' (getlinelen)
  1052.     end
  1053.     undoend
  1054.   end
  1055.  
  1056.   // delete a block
  1057.   function deleteblock2
  1058.     if getmarkbuf == getcurrbuf then
  1059.       deleteblock
  1060.     else
  1061.       if wintype? "edit" then
  1062.         if _DelLine == 'y' then
  1063.           delline
  1064.         end
  1065.       end
  1066.     end
  1067.   end
  1068.  
  1069.   // prompt to enter character literally
  1070.   function literal
  1071.     say "Enter Literal..."
  1072.     queue <char> (char getkey & 0ffh)
  1073.   end
  1074.  
  1075.   // ascii chart with character entry
  1076.   function asciilist
  1077.     buffer = asciibuf
  1078.     // name it so the position can be remembered
  1079.     setbufname "_asc"
  1080.     character = (popup buffer '' 13) [10]
  1081.     destroybuf
  1082.     if character then
  1083.       queue <char> character
  1084.     end
  1085.   end
  1086.  
  1087.   // support for file name completion (open prompts only)
  1088.   function askcomplete
  1089.     if gethistname == "_load" then
  1090.       filespec = gettext
  1091.       if filespec then
  1092.         if not pos "*.*" filespec then
  1093.           filespec = filespec + (if? (pos '.' filespec) '*' "*.*")
  1094.         end
  1095.       else
  1096.         filespec = "*.*"
  1097.       end
  1098.       filespec = qualify filespec (getbufname (getwinbuf (getprevwin (getcurrwin))))
  1099.       file = pickfile filespec (onname filespec 't')
  1100.       if file then
  1101.         col 1
  1102.         delchar (getlinelen)
  1103.         writetext file
  1104.         return file
  1105.       end
  1106.     end
  1107.   end
  1108.  
  1109.   // get the first line of text in the default mark
  1110.   function getmarktext
  1111.     if mark? then
  1112.       oldbuf = gotobuf (getmarkbuf)
  1113.       pushcursor
  1114.       row (getmarktop)
  1115.       text = case getmarktype
  1116.                // line mark
  1117.                when 'l'
  1118.                  gettext (getlinebeg)
  1119.                // column mark
  1120.                when 'k'
  1121.                  // convert left,right to actual columns
  1122.                  // (in case there are real tabs)
  1123.                  start = actualcol (getmarkleft)
  1124.                  gettext start (actualcol (getmarkright)) - start + 1
  1125.                // char/stream marks
  1126.                otherwise
  1127.                  gettext (getmarkleft) (getmarkcols)
  1128.              end
  1129.       popcursor
  1130.       gotobuf oldbuf
  1131.       return text
  1132.     end
  1133.   end
  1134.  
  1135.   // copy or copy-append to the clipboard
  1136.   function copy (options)
  1137.  
  1138.     if not mark? then
  1139.       // use current line if nothing marked?
  1140.       if _ClipLine <> 'y' then
  1141.         say "No mark exists"
  1142.         return
  1143.       end
  1144.       undobegin
  1145.       markline
  1146.       tempmark = TRUE
  1147.     end
  1148.  
  1149.     // copy to ms windows
  1150.     if pos 'w' options then
  1151.       if not saveblock "^:c"
  1152.          (if? getmarktype <> 'l' and getmarkrows == 1 'bx' 'x') then
  1153.         msgbox "The Windows clipboard is not available."
  1154.       end
  1155.       display
  1156.     else
  1157.       currentbuf = getcurrbuf
  1158.       clip = _ClipName
  1159.       destroymark clip
  1160.       copymark (getmarkuse) clip
  1161.  
  1162.       // copy append
  1163.       if (pos 'a' options) and (buffer? clip) then
  1164.         if getmarktype <> 'l' then
  1165.           insline '' '' (getlines clip) clip
  1166.         end
  1167.         copyblock clip clip 1 (getlines clip)
  1168.         markline 1 (getlines clip) clip clip
  1169.  
  1170.       // copy
  1171.       else
  1172.         destroybuf clip
  1173.         createbuf clip
  1174.         copyblock clip clip
  1175.         if getmarktype == 'l' then
  1176.           delline 1 1 clip
  1177.         end
  1178.       end
  1179.       currbuf currentbuf
  1180.     end
  1181.     if pos 'd' options then
  1182.       deleteblock
  1183.     end
  1184.     if tempmark then
  1185.       if not pos 'd' options then
  1186.         destroymark
  1187.       end
  1188.       undoend
  1189.     end
  1190.   end
  1191.  
  1192.   // cut or cut-append to the clipboard
  1193.   function cut (options)
  1194.     copy options + 'd'
  1195.   end
  1196.  
  1197.   // enter a character or string into the current prompt
  1198.   function write (charstring)
  1199.     writetext charstring
  1200.   end
  1201.  
  1202.  
  1203. //--------------------------------------------------------------------
  1204. // Edit windows
  1205. //--------------------------------------------------------------------
  1206.  
  1207. object edit
  1208.  
  1209.   // mark a paragraph
  1210.   function markpara (options)
  1211.  
  1212.     if getlinelen then
  1213.  
  1214.       undobegin
  1215.       destroymark
  1216.  
  1217.       // find the beginning of the paragraph
  1218.       pushcursor
  1219.       // check for mark-to-end of paragraph
  1220.       if not pos 'e' options then
  1221.         while up and getlinelen end
  1222.         if not getlinelen then down end
  1223.         markline
  1224.       end
  1225.       popcursor
  1226.  
  1227.       // find the end of the paragraph
  1228.       pushcursor
  1229.       while down and getlinelen end
  1230.       if not getlinelen then up end
  1231.       markline
  1232.       popcursor
  1233.  
  1234.       undoend
  1235.  
  1236.       return 1
  1237.     end
  1238.   end
  1239.  
  1240.   private variable baflag
  1241.  
  1242.   // setup for insert-above (copy, move, paste - lineblocks only)
  1243.   private function begabove (lineop)
  1244.     baflag = ''
  1245.     undobegin
  1246.     if (lineop or getmarktype == 'l') and _InsAbove == 'y' then
  1247.       baflag = 1
  1248.       if not up then
  1249.         insabove
  1250.         up
  1251.         baflag = 2
  1252.       end
  1253.     end
  1254.   end
  1255.  
  1256.   // end insert-above
  1257.   private function endabove
  1258.     case baflag
  1259.       when 1 down
  1260.       when 2 delline
  1261.     end
  1262.     undoend
  1263.   end
  1264.  
  1265.   // paste or paste-over from the clipboard
  1266.   function paste (options)
  1267.     // paste from ms windows
  1268.     if pos 'w' options then
  1269.       oldbuf = getcurrbuf
  1270.       markname = 'T'
  1271.       if loadbuf "^:c" then
  1272.         markchar 1 (getlinelen (getlines)) 1 (getlines) markname
  1273.         tempbuf = gotobuf oldbuf
  1274.       end
  1275.     else
  1276.       markname = _ClipName
  1277.     end
  1278.     if mark? markname then
  1279.       destroymark
  1280.       copymark markname (getmarkuse)
  1281.       if pos 'o' options then
  1282.         copyblockover
  1283.       else
  1284.         begabove
  1285.         copyblock
  1286.         endabove
  1287.       end
  1288.       if tempbuf then
  1289.         destroybuf tempbuf
  1290.       end
  1291.     else
  1292.       display
  1293.       say "Nothing to paste"
  1294.     end
  1295.   end
  1296.  
  1297.   // clear the clipboard
  1298.   function clear
  1299.     destroybuf _ClipName
  1300.   end
  1301.  
  1302.   // copy a block
  1303.   function copyblock2
  1304.     if mark? then
  1305.       begabove
  1306.       if not copyblock then
  1307.         say "Copy failed" 'b'
  1308.       end
  1309.       endabove
  1310.     else
  1311.       if _CopyLine == 'y' then
  1312.         copyblock '*l'
  1313.       end
  1314.     end
  1315.   end
  1316.  
  1317.   // move a block
  1318.   function moveblock2
  1319.     begabove
  1320.     if getmarktop < getviewtop then
  1321.       y = 1 + getrow - (apparentrow  getviewtop - getrow)
  1322.     end
  1323.     if moveblock then
  1324.       if y then
  1325.         adjustrow y
  1326.       end
  1327.     else
  1328.       say "Move failed" 'b'
  1329.     end
  1330.     endabove
  1331.   end
  1332.  
  1333.   // move a block over text
  1334.   function moveblockover
  1335.     if mark? then
  1336.       undobegin
  1337.       // use a temporary clipboard
  1338.       clip = _ClipName
  1339.       prf.ClipName = 'T'
  1340.       copy
  1341.       fillblock ' '
  1342.       paste 'o'
  1343.       prf.ClipName = clip
  1344.       destroybuf 'T'
  1345.       undoend
  1346.     end
  1347.   end
  1348.  
  1349.   // reformat a block or the current paragraph
  1350.   function formatblock2 (options)
  1351.     if not options then
  1352.       options = _FormatOpt
  1353.     end
  1354.  
  1355.     // advance cursor
  1356.     if not getlinelen and (pos 'c' options) then
  1357.       loop
  1358.         if not down then
  1359.           return
  1360.         end
  1361.         if getlinelen then
  1362.           break
  1363.         end
  1364.       end
  1365.     end
  1366.  
  1367.     undobegin
  1368.     if not mark? then
  1369.       if markpara options then
  1370.         markcolumn (apparentcol (getcol)) _RMargin (getmarktop) (getmarkbot)
  1371.         flag = ON
  1372.       end
  1373.     end
  1374.     // special case for single lines
  1375.     if getmarkrows == 1 and getcol < getlinebeg then
  1376.       delchar getlinebeg - getcol
  1377.     else
  1378.       formatblock _LMargin _RMargin options
  1379.     end
  1380.  
  1381.     if flag then
  1382.       // advance cursor
  1383.       if pos 'c' options then
  1384.         row getmarkbot + 1
  1385.       end
  1386.       destroymark
  1387.     end
  1388.     undoend
  1389.   end
  1390.  
  1391.   // simple text quoting support for a block or the current paragraph
  1392.   function quote
  1393.     undobegin
  1394.     if getmarkbuf <> getcurrbuf then
  1395.       tempmark = TRUE
  1396.       oldmark = usemark 'T'
  1397.       markpara
  1398.     end
  1399.     if mark? then
  1400.       shiftblock 1 '' '>'
  1401.       if tempmark then
  1402.         destroymark
  1403.         usemark oldmark
  1404.       end
  1405.     else
  1406.       say "Nothing to quote"
  1407.     end
  1408.     undoend
  1409.   end
  1410.  
  1411.   // sort a block
  1412.   function sortblock2
  1413.     if mark? then
  1414.       if runcfg "sort" then
  1415.         say "Sorting..."
  1416.         sortblock _SortOpt
  1417.         display
  1418.       end
  1419.     else
  1420.       say "No block"
  1421.     end
  1422.   end
  1423.  
  1424.   // prompt to fill a block with a string
  1425.   function fillblock2
  1426.     askx "Enter fill string" '' "fillblock"
  1427.   end
  1428.  
  1429.   // prompt to save a block
  1430.   function saveblock2 (options file)
  1431.     variable c1, c2
  1432.     if mark? then
  1433.       if not file then
  1434.         file = ask "Save block as" "_load"
  1435.       end
  1436.       if file then
  1437.         file = qualify file (getbufname)
  1438.         addhistory "_load" file
  1439.         if fileattr? file 'r' then
  1440.           say "Read Only!" 'b'
  1441.         else
  1442.           action = locase (askrac file)
  1443.           if pos action "ra" then
  1444.             send "oncomment" file ref c1 ref c2
  1445.             options = _SaveOpt + options
  1446.             if not saveblock file
  1447.                     (if? (pos 'e' options) 'e' + _TabWidth) + options +
  1448.                     (if? action == 'a' 'a')
  1449.                     '' '' '' (if? c1 c1 + _FoldSign) c2 then
  1450.               msgbox "Save Failed!" "Error!" 'b'
  1451.             end
  1452.           end
  1453.         end
  1454.       end
  1455.     else
  1456.       say "No marked block" 'b'
  1457.     end
  1458.   end
  1459.  
  1460.   // left justify, center, or right justify a block
  1461.   function justblock2 (options)
  1462.     justblock options '' _LMargin _RMargin
  1463.   end
  1464.  
  1465.   // destroy open and closed folds
  1466.   function destroyfold2
  1467.     undobegin
  1468.     if not fold? then
  1469.       closefold
  1470.     end
  1471.     destroyfold
  1472.     undoend
  1473.   end
  1474.  
  1475.   // do fold operations on entire file
  1476.   function foldall (options)
  1477.     foldblock options '*a'
  1478.   end
  1479.  
  1480.   // fold a block or the current paragraph
  1481.   function foldblock2
  1482.     undobegin
  1483.     if mark? then
  1484.       foldblock
  1485.     elseif markpara then
  1486.       foldblock
  1487.       destroymark
  1488.     end
  1489.     undoend
  1490.   end
  1491.  
  1492.   // fold a block and destroy subfolds
  1493.   function foldflat
  1494.     undobegin
  1495.     foldblock 'ds'
  1496.     foldblock
  1497.     undoend
  1498.   end
  1499.  
  1500.   // fold or unfold a line
  1501.   function foldline (options)
  1502.     undobegin
  1503.     oldmark = usemark 'T'
  1504.     markline
  1505.     unfold = pos 'u' options
  1506.     if fold? then
  1507.       foldblock 'd'
  1508.       if not unfold or getmarkrows > 1 then
  1509.         bottom = actualrow (if? unfold -1 1) (getmarkbot)
  1510.         if not (getfold 'o' bottom) then
  1511.           markline (getrow) bottom
  1512.         end
  1513.         foldblock
  1514.       end
  1515.     else
  1516.       if not unfold then
  1517.         foldblock
  1518.       end
  1519.     end
  1520.     destroymark
  1521.     usemark oldmark
  1522.     undoend
  1523.   end
  1524.  
  1525.   // detab or entab the current file
  1526.   // (+width=detab, -width=entab)
  1527.   function tabfile (width)
  1528.     tabblock (if? width width _TabWidth) '*a'
  1529.   end
  1530.  
  1531.   // insert a line after the current line with autoindent
  1532.   function insline2
  1533.     undobegin
  1534.     insline
  1535.     if setting? 'A' then
  1536.       if getlinelen then
  1537.         col (getlinebeg)
  1538.       else
  1539.         nextline = getrow + 2
  1540.         if getlinelen nextline then
  1541.           col (getlinebeg nextline)
  1542.         end
  1543.       end
  1544.     end
  1545.     down
  1546.     undoend
  1547.   end
  1548.  
  1549.   // swap the current line with the next line
  1550.   function swapline
  1551.     moveblock '*l' '' '' (actualrow 1)
  1552.   end
  1553.  
  1554.   // center the current line
  1555.   function centerline
  1556.     justblock 'c' '*l' _LMargin _RMargin
  1557.   end
  1558.  
  1559.   // comment or uncomment a line
  1560.   function commentline (c1 c2)
  1561.     if not c1 then
  1562.       send "oncomment" (getbufname) ref c1 ref c2
  1563.       if not c1 then
  1564.         c1 = '>'
  1565.       end
  1566.     end
  1567.     undobegin
  1568.     column = getlinebeg
  1569.     if (gettext column  length c1) == c1 then
  1570.       delchar  length c2  getlinelen - length c2 + 1
  1571.       delchar  length c1  column
  1572.     elseif getlinelen then
  1573.       instext c1 (getlinebeg)
  1574.       if column then
  1575.         ovltext c2 getlinelen + 1
  1576.       end
  1577.     end
  1578.     down
  1579.     undoend
  1580.   end
  1581.  
  1582.   // find previous word
  1583.   function prevword
  1584.     oldcolumn = getcol
  1585.     while (poschar _CSet (getchar)) and left do end
  1586.     if oldcolumn <> getcol then
  1587.       if poschar _CSet (getchar) then
  1588.         return
  1589.       end
  1590.       if oldcolumn - getcol > 1 then
  1591.         right
  1592.         return
  1593.       end
  1594.     end
  1595.     find _CSet '[r'
  1596.     while (poschar _CSet (getchar getcol - 1)) and left do end
  1597.   end
  1598.  
  1599.   // find next word
  1600.   function nextword
  1601.     while poschar _CSet (getchar) do
  1602.       right
  1603.     end
  1604.     find _CSet '['
  1605.   end
  1606.  
  1607.   // change the case of the word at the cursor
  1608.   function caseword (options charset)
  1609.     undobegin
  1610.     oldmark = usemark 'T'
  1611.     markword charset
  1612.     caseblock options
  1613.     destroymark
  1614.     usemark oldmark
  1615.     undoend
  1616.   end
  1617.  
  1618.   // open the filename at the cursor
  1619.   function openword (charset)
  1620.     file = getword (if? charset charset _CSetB)
  1621.     if file then
  1622.       open file
  1623.     end
  1624.   end
  1625.  
  1626.   // delete the character at the cursor
  1627.   function delchar2
  1628.     undobegin
  1629.     if getcol > getlinelen and _DelJoin == 'y' then
  1630.       joinline
  1631.     else
  1632.       delchar
  1633.       if setting? 'L' then
  1634.         livewrap
  1635.       end
  1636.     end
  1637.     undoend
  1638.   end
  1639.  
  1640.   // backspace
  1641.   function backsp
  1642.     undobegin
  1643.     if getcol > 1 then
  1644.       left
  1645.       if not insert? and _BakOvl == 'y' then
  1646.         ovltext ' '
  1647.       else
  1648.         delchar
  1649.         if setting? 'L' then
  1650.           livewrap
  1651.         end
  1652.       end
  1653.     elseif getrow > 1 and _BakJoin == 'y' then
  1654.       up
  1655.       col getlinelen + 1
  1656.       joinline
  1657.     end
  1658.     undoend
  1659.   end
  1660.  
  1661.   // delete right word
  1662.   function delword (charset)
  1663.     if not charset then
  1664.       charset = _CSet
  1665.     end
  1666.     undobegin
  1667.     if getcol > getlinelen then
  1668.       joinline
  1669.     else
  1670.       p = posnot charset (gettext (getcol))
  1671.       if p > 1 then
  1672.         delchar p - 1
  1673.       end
  1674.       delchar (
  1675.         if p then
  1676.           if (pos (getchar) ' \t') and
  1677.                 (p == 1 or getcol == 1 or
  1678.                 (posnot charset (getchar getcol - 1))) then
  1679.             (posnot ' \t' (gettext (getcol))) - 1
  1680.           else
  1681.             p == 1
  1682.           end
  1683.         else
  1684.           getlinelen
  1685.         end
  1686.       )
  1687.     end
  1688.     if setting? 'L' then
  1689.       livewrap
  1690.     end
  1691.     undoend
  1692.   end
  1693.  
  1694.   // splitline with autoindent
  1695.   function splitline2
  1696.     undobegin
  1697.     b = apparentcol (getlinebeg)
  1698.     if splitline then
  1699.       if not setting? 'A' then
  1700.         b = _LMargin
  1701.       end
  1702.       if b > 1 then
  1703.         pushcursor
  1704.         down
  1705.         oldmark = usemark 'T'
  1706.         markline
  1707.         c = apparentcol (getcol)
  1708.         shiftblock (if? c > b b c) - 1
  1709.         destroymark
  1710.         usemark oldmark
  1711.         popcursor
  1712.       end
  1713.     end
  1714.     undoend
  1715.   end
  1716.  
  1717.   // <enter> key behavior
  1718.   function enter
  1719.  
  1720.     // terminate a word for text translation
  1721.     lastrow = getrow
  1722.     if getcol == getlinelen + 1 and getlinelen then
  1723.       if setting? 'T' then
  1724.         send <char> ' '
  1725.       end
  1726.     end
  1727.  
  1728.     if getrow == lastrow then
  1729.       case (if? (insert?) _EnterIns _EnterOvl)
  1730.         when 'i'
  1731.           insline2
  1732.         when 's'
  1733.           if fold? then
  1734.             insline2
  1735.           else
  1736.             startcolumn = apparentcol (getlinebeg)
  1737.             len = getlinelen
  1738.             splitline2
  1739.             down
  1740.             if setting? 'A' then
  1741.               if len then
  1742.                 col (actualcol startcolumn)
  1743.               end
  1744.             else
  1745.               startcolumn = _LMargin
  1746.               col (actualcol (if? startcolumn startcolumn 1))
  1747.             end
  1748.           end
  1749.         otherwise
  1750.           down
  1751.           col (if? (getlinelen) (getlinebeg) (actualcol _LMargin))
  1752.       end
  1753.     end
  1754.   end
  1755.  
  1756.  
  1757.   // for use by variable tab right
  1758.   function vtabr
  1759.     for i = 1 to arg do
  1760.       if (arg i) > getcol then
  1761.         return arg i
  1762.       end
  1763.     end
  1764.     return 0
  1765.   end
  1766.  
  1767.   // for use by variable tab left
  1768.   function vtabl
  1769.     for i = arg downto 1 do
  1770.       if (arg i) < getcol then
  1771.         return arg i
  1772.       end
  1773.     end
  1774.     return 0
  1775.   end
  1776.  
  1777.   // tab support
  1778.   function tabfunc (next)
  1779.  
  1780.     // toggle between hex display/entry mode
  1781.     if windowflag 'h?' then
  1782.       windowflag (if? (windowflag "12?") "-12" "+1")
  1783.       return
  1784.     end
  1785.  
  1786.     oldcolumn = apparentcol (getcol)
  1787.  
  1788.     // smart tabs
  1789.     if setting? 'S' then
  1790.       prevline = getrow - 1
  1791.       while prevline and not (getlinelen prevline) do
  1792.         prevline = prevline - 1
  1793.       end
  1794.       if prevline then
  1795.         pushcursor
  1796.         row prevline
  1797.         send (if? next "nextword" "prevword")
  1798.         if prevline == getrow then
  1799.           newcolumn = apparentcol (getcol)
  1800.         end
  1801.         popcursor
  1802.       end
  1803.     end
  1804.  
  1805.     // variable tabs
  1806.     if not newcolumn then
  1807.       if setting? 'V' then
  1808.         newcolumn = eval (if? next "vtabr " "vtabl ") + _VarTabs
  1809.       end
  1810.  
  1811.       // standard fixed interval tabs
  1812.       if not newcolumn then
  1813.         width = getbuftabs
  1814.         if not width then
  1815.           width = _TabWidth
  1816.           if not width then
  1817.             width = 8
  1818.           end
  1819.         end
  1820.         newcolumn = oldcolumn +
  1821.                       if next then
  1822.                         width - (oldcolumn - 1) mod width
  1823.                       elseif oldcolumn > 1 then
  1824.                         -((oldcolumn - 2) mod width + 1)
  1825.                       end
  1826.       end
  1827.     end
  1828.  
  1829.     // move to tabstop and shift text if needed
  1830.     // (check for real tabs)
  1831.     if newcolumn then
  1832.       newcolumn = actualcol newcolumn
  1833.       if (pos 'h' _TabOpt) and insert? then
  1834.         realtab = (pos 'r' _TabOpt) and getbuftabs and not (setting? "SV")
  1835.         oldcolumn = actualcol oldcolumn
  1836.         if newcolumn < oldcolumn then
  1837.           if not posnot ' \t' (gettext newcolumn oldcolumn - newcolumn) then
  1838.             delchar oldcolumn - newcolumn newcolumn
  1839.           end
  1840.         elseif newcolumn > oldcolumn then
  1841.           // insert real tab or spaces
  1842.           writetext (if? realtab '\t'
  1843.                         '': ((apparentcol newcolumn) - (apparentcol oldcolumn)))
  1844.           return
  1845.         end
  1846.       end
  1847.       col newcolumn
  1848.     end
  1849.   end
  1850.  
  1851.   // tab left and right
  1852.   function tabright    tabfunc 1
  1853.   function tableft     tabfunc
  1854.  
  1855.   // prompt to verify close
  1856.   function close?
  1857.     if bufchanged? and not getprevcurs then
  1858.       savechanges = popup "ync" "Save changes to " +
  1859.                                  (onname (getname (getbufname)) 't') + '?'
  1860.       if savechanges == "Yes" then
  1861.         if not save then
  1862.           return ''
  1863.         end
  1864.       end
  1865.       icompare savechanges "Yes" "No"
  1866.     else
  1867.       1
  1868.     end
  1869.   end
  1870.  
  1871.   // close an edit window
  1872.   function close (options)
  1873.     if pos 's' options then
  1874.       if save then
  1875.         pass
  1876.       end
  1877.     elseif close? then
  1878.       pass
  1879.     end
  1880.   end
  1881.  
  1882.   // open and insert prompt
  1883.   function askinsert (file)
  1884.     if not file then
  1885.       file = askfile "File to insert into " + (onname (getname (getbufname)))
  1886.                      "Open and Insert"
  1887.     end
  1888.     if file then
  1889.       begabove TRUE
  1890.       old_size = getlines
  1891.       // addhistory not needed for open
  1892.       if open file 'i' then
  1893.         // mark the inserted text
  1894.         if not (dir? (getbufname)) then
  1895.           if getlines > old_size then
  1896.             markline  getrow + 1  getrow + getlines - old_size
  1897.           end
  1898.         end
  1899.       end
  1900.       endabove
  1901.     end
  1902.   end
  1903.  
  1904.   // prompt to change the current file name
  1905.   function askname
  1906.     newname = ask  "Rename " + (onname (getname (getbufname))) + " to"  "_load"
  1907.     if newname then
  1908.       case setname newname
  1909.         when -1 say "Failed" 'b'
  1910.         when -2 say "Failed - file already loaded" 'b'
  1911.         otherwise
  1912.           addhistory "_load" (getbufname)
  1913.       end
  1914.     end
  1915.   end
  1916.  
  1917.   // search and replace with messages and highlighting
  1918.   function search2 (search_str reverse again)
  1919.     variable opt, rpl
  1920.     n = search search_str reverse again ref opt ref rpl
  1921.     if n then
  1922.       // replace occurred
  1923.       if rpl then
  1924.         display
  1925.         say (thousands n) + " changes made"
  1926.       // count occurrences
  1927.       elseif pos 'a' opt then
  1928.         display
  1929.         say (thousands n) + " occurrences of '" + search_str + "' found"
  1930.       // search only
  1931.       else
  1932.         onfound n
  1933.       end
  1934.     else
  1935.       display
  1936.       say "'" + search_str + "' not found"  'b'
  1937.     end
  1938.     return n
  1939.   end
  1940.  
  1941.   // edit fields/group boxes for find/repl dialog boxes
  1942.   variable f1, f2, g1, g2
  1943.  
  1944.   // retrieve history in find/repl dlgbox fields and options
  1945.   function findupd
  1946.     variable searchstr, replstr, options
  1947.  
  1948.     n = splitstr '' (gettext) ref searchstr ref replstr ref options
  1949.     if n == 2 then
  1950.       options = replstr
  1951.       replstr = ''
  1952.     end
  1953.  
  1954.     // default options
  1955.     if not options and n <= 1 then
  1956.       options = _SearchOpt + (if? f2 _ReplaceOpt '')
  1957.     end
  1958.  
  1959.     // find string
  1960.     buffer = getwinbuf f1
  1961.     delchar MAX_COL 1 '' buffer
  1962.     instext searchstr 1 '' buffer
  1963.  
  1964.     // replace string/filestr
  1965.     if f2 then
  1966.       buffer = getwinbuf f2
  1967.       delchar MAX_COL 1 '' buffer
  1968.       instext replstr 1 '' buffer
  1969.     end
  1970.  
  1971.     // set search/replace options
  1972.     setgroupbox options "iwxa"  g1
  1973.     setgroupbox options "rbgs"  g2
  1974.     col getlinelen + 1
  1975.   end
  1976.  
  1977.   // find/repl option group boxes
  1978.   private function frdlg (y options)
  1979.     // group box 1
  1980.     g1 = groupbox '' 3 y
  1981.       (menu ''
  1982.          item " [ ] &Ignore Case"
  1983.          item " [ ] &Whole Words"
  1984.          item " [ ] Regular E&Xpression "
  1985.          item (if? f2
  1986.                   " [ ] Replace &All"
  1987.                   " [ ] &Count Occurrences")
  1988.        end ) '' _SearchOpt + (if? f2 _ReplaceOpt '')
  1989.                'iwxa'
  1990.  
  1991.     // group box 2
  1992.     g2 = groupbox '' 29 y
  1993.       (menu ''
  1994.          item " [ ] &Reverse Search"
  1995.          item " [ ] Marked &Block Only  "
  1996.          item " [ ] &Global Search"
  1997.          item " [ ] Skip &Folds"
  1998.        end) '' _SearchOpt "rbgs"
  1999.  
  2000.     button "O&k"    56 2 8
  2001.     button "Cancel" 56 4 8
  2002.   end
  2003.  
  2004.   // find dialog box
  2005.   function finddlg
  2006.     variable searchstr, options1, options2
  2007.     dialog "Find" 66 8 'cp'
  2008.     f1 = field "&Search for: >" 3 2  38 '' "_find" whenselect "findupd"
  2009.     f2 = ''
  2010.     frdlg 4
  2011.     if (getdialog ref searchstr ref options1 ref options2) == 'Ok' then
  2012.       joinstr '' searchstr options1 + options2
  2013.     end
  2014.   end
  2015.  
  2016.   // replace dialog box
  2017.   function repldlg
  2018.     variable searchstr, replstr, options1, options2
  2019.     dialog "Replace" 66 10 'cp'
  2020.     f1 = field "&Search for:   >" 3 2  36 '' "_find" whenselect "findupd"
  2021.     f2 = field "Re&place with: >" 3 4  36 '' "_find" whenselect "findupd"
  2022.     frdlg 6 'r'
  2023.     if (getdialog ref searchstr ref replstr ref options1 ref options2) == 'Ok' then
  2024.       joinstr '' searchstr replstr options1 + options2
  2025.     end
  2026.   end
  2027.  
  2028.   // find prompt
  2029.   function askfind (reverse)
  2030.     search_string = if _PromptStyle == 'd' then
  2031.                       finddlg
  2032.                     else
  2033.                       ask "[string/abgirswx] Find"  "_find"
  2034.                     end
  2035.     if search_string then
  2036.       search2 search_string reverse
  2037.       addhistory "_find" search_string
  2038.     end
  2039.   end
  2040.  
  2041.   // replace prompt
  2042.   function askrepl (reverse)
  2043.     search_string = if _PromptStyle == 'd' then
  2044.                       repldlg
  2045.                     else
  2046.                       ask "[string/replstr/abgirswx] Repl"  "_find"
  2047.                     end
  2048.     if search_string then
  2049.       if (splitstr '' search_string) < 3 then
  2050.         search_string = search_string + '/'
  2051.       end
  2052.       search2 search_string reverse
  2053.       addhistory "_find" search_string
  2054.     end
  2055.   end
  2056.  
  2057.   // do the last find/replace operation
  2058.   // (reverse=r reverses the search direction)
  2059.   function findlast (reverse)
  2060.     search2 (gethiststr "_find") reverse TRUE
  2061.   end
  2062.  
  2063.   // incremental search
  2064.   function isearch
  2065.  
  2066.     variable search_string
  2067.  
  2068.     oldtitle = gettitle
  2069.     repeat
  2070.  
  2071.       settitle  "I-search for [" + search_string + "] "
  2072.       keycode = getkey
  2073.       options = _SearchOpt
  2074.       new_char = ''
  2075.  
  2076.       case  keycode
  2077.  
  2078.         when <backspace>
  2079.           if search_string then
  2080.             popcursor
  2081.             search_string = if length search_string > 1 then
  2082.                               search_string [1 .. length search_string - 1]
  2083.                             else
  2084.                               ''
  2085.                             end
  2086.             if not search_string then
  2087.               display
  2088.             end
  2089.             options = '*'
  2090.           end
  2091.  
  2092.         when <ctrl p>, <ctrl r>
  2093.           options = 'r'
  2094.  
  2095.         when <ctrl n>, <ctrl l>
  2096.           // do nothing
  2097.  
  2098.         when <ctrl g>, <ctrl b>
  2099.           options = 'g'
  2100.  
  2101.         otherwise
  2102.           keyname = geteventname keycode
  2103.           if length keyname == 3 then
  2104.             pushcursor
  2105.             new_char = keyname [2]
  2106.             options = '*'
  2107.           else
  2108.  
  2109.             // restore window title
  2110.             settitle oldtitle
  2111.             display
  2112.  
  2113.             // clear all pushed cursors
  2114.             popcursor "ad"
  2115.             addhistory "_find" search_string
  2116.  
  2117.             if keycode <> <enter> and keycode <> <esc> then
  2118.               queuekey keycode
  2119.             end
  2120.  
  2121.             done = TRUE
  2122.           end
  2123.       end
  2124.  
  2125.       if not done and (search_string or new_char) then
  2126.         new_string = concat search_string new_char
  2127.         str_length = find new_string  _SearchOpt + options
  2128.         if str_length then
  2129.           onfound str_length
  2130.           search_string = new_string
  2131.         else
  2132.           say  new_string + " not found"  'b'
  2133.           if new_char then
  2134.             popcursor
  2135.           end
  2136.           onfound  length search_string
  2137.         end
  2138.       end
  2139.  
  2140.     until done
  2141.   end
  2142.  
  2143.   // prompt to find occurrences
  2144.   function askfindo
  2145.     runmacro (bootpath "macro\\findo.x")
  2146.   end
  2147.  
  2148.   // find all occurrences of last find string
  2149.   function findlasto
  2150.     runmacro (bootpath "macro\\findo.x") '' (gethiststr "_find")
  2151.   end
  2152.  
  2153.   // find matching character (){}[]<>
  2154.   function gotomatch2
  2155.     if gotomatch "(){}[]<>" then
  2156.       onfound 1
  2157.     else
  2158.       say "Not found" 'b'
  2159.     end
  2160.   end
  2161.  
  2162.   // goto line
  2163.   function row2 (line)
  2164.     case line [1]
  2165.       when '+'   down line [2 : TO_END]
  2166.       when '-'   up   line [2 : TO_END]
  2167.       otherwise  row (if? line > getlines (getlines) line)
  2168.     end
  2169.     onfound
  2170.   end
  2171.  
  2172.   // goto line prompt
  2173.   function askrow
  2174.     askx "Line number" "_line" "row2"
  2175.   end
  2176.  
  2177.   // set a quick bookmark
  2178.   function quickbook
  2179.     loop
  2180.       i = i + 1
  2181.       bookmark = "Book" + i
  2182.       if not book? bookmark then
  2183.         break
  2184.       end
  2185.     end
  2186.     setbook bookmark
  2187.     display
  2188.     say "Bookmark " + bookmark + " set"
  2189.   end
  2190.  
  2191.   // place a bookmark
  2192.   function placebook (bookmark)
  2193.     if not bookmark then
  2194.       bookmark = ask "Bookmark Name" "_book"
  2195.     end
  2196.     if bookmark then
  2197.       setbook bookmark
  2198.       display
  2199.       say "Bookmark '" + bookmark + "' set"
  2200.     end
  2201.   end
  2202.  
  2203.  
  2204.   // Go to the compiler error on the current line of a compiler
  2205.   // error output file. This function recognizes compiler errors
  2206.   // of the form:
  2207.   //
  2208.   //   <text>  Filename.ext  <text>  Linenumber  <text> : Message
  2209.   //
  2210.   // (implemented by using the 'parse' builtin function with regular
  2211.   // expression searching)
  2212.  
  2213.   function gotoerror
  2214.     variable filename, line, message
  2215.  
  2216.     // filename charclass to use (max closure without the period)
  2217.     fileset = "[a-zA-Z0-9_\-/\\\\@~:^!#$%&`']#"
  2218.  
  2219.     // parse the current line into filename/line/message variables
  2220.     if parse '.*{' + fileset + '\\.' + fileset + "}.*{[0-9]#}.*:{.*}$"
  2221.              (gettext) 'x' ref filename ref line ref message then
  2222.  
  2223.       // open the file
  2224.       if open filename then
  2225.  
  2226.         // get the real line number if folds are present
  2227.         if (getfold 'n') and
  2228.            (loadbuf (getbufname) '' (hex2bin _LineDlm) 'x') then
  2229.           row line
  2230.           line = line - (find _FoldSign 'ar')
  2231.           destroybuf
  2232.         end
  2233.  
  2234.         row line
  2235.  
  2236.         // open folds until the line is exposed
  2237.         while (getfold 'c') and getrow <> line do
  2238.           openfold
  2239.           row line
  2240.         end
  2241.  
  2242.         col (getlinebeg)
  2243.         send "onfound"
  2244.         say  message + '  '
  2245.         return
  2246.       end
  2247.     end
  2248.     display
  2249.     say "Compiler message not recognized. "
  2250.   end
  2251.  
  2252.  
  2253.   // start, stop, or do autosave
  2254.   function autosave (seconds)
  2255.     if not arg then
  2256.       if bufchanged? then
  2257.         save
  2258.       end
  2259.     elseif seconds <= 0 then
  2260.       destroytimer "asav"
  2261.     else
  2262.       setrepeat "asav" seconds * 1000  '' "autosave"
  2263.     end
  2264.   end
  2265.  
  2266.   // prompt for autosave interval in seconds
  2267.   function askasave
  2268.     seconds = ask "Autosave interval in secs (-1=disable)"
  2269.     if seconds then
  2270.       autosave seconds
  2271.     end
  2272.   end
  2273.  
  2274.   // highlight all occurrences of the word at the cursor
  2275.   function hiliteword
  2276.     runmacro2 "hilitewd"
  2277.   end
  2278.  
  2279.   // live word wrap support
  2280.   function livewrap
  2281.  
  2282.     if fold? then
  2283.       return
  2284.     end
  2285.  
  2286.     startcol = apparentcol (getlinebeg)
  2287.     nextrow = getrow + 1
  2288.     if getrow < getlines and (getlinelen nextrow) then
  2289.       c = apparentcol (getlinebeg nextrow) nextrow
  2290.       startcol = if? c < startcol  c  startcol
  2291.     elseif not getlinelen or not (setting? 'A') then
  2292.       startcol = _LMargin
  2293.     end
  2294.  
  2295.     c = apparentcol (getcol)
  2296.     if c < startcol then
  2297.       startcol = c
  2298.     end
  2299.  
  2300.     if getlinelen then
  2301.       undobegin
  2302.       saved_char = getchar
  2303.       ovltext '\xFD'
  2304.  
  2305.       // mark to the end of the paragraph
  2306.       pushcursor
  2307.       top = getrow
  2308.       while down and getlinelen do end
  2309.       if not getlinelen then
  2310.         up
  2311.       end
  2312.       bottom = getrow
  2313.       popcursor
  2314.  
  2315.       // reformat
  2316.       oldmark = usemark 'T'
  2317.       markcolumn startcol _RMargin top bottom
  2318.       formatblock '' '' "kr"
  2319.       destroymark
  2320.       usemark oldmark
  2321.  
  2322.       // find the original cursor position
  2323.       col 1
  2324.       find '\xFD' '*'
  2325.       ovltext (if? saved_char saved_char ' ')
  2326.  
  2327.       undoend
  2328.     end
  2329.   end
  2330.  
  2331.   // enter a character or string at the cursor, with support for:
  2332.   //   - match character
  2333.   //   - translate
  2334.   //   - standard word wrap
  2335.   //   - live word wrap
  2336.   //   - hex entry mode
  2337.  
  2338.   function write (write_str)
  2339.  
  2340.     // group together as one undoable operation
  2341.     undobegin
  2342.  
  2343.     // hex entry mode
  2344.     if windowflag 'h?' then
  2345.       if windowflag '12?' then
  2346.         while write_str do
  2347.           hexchar = upcase write_str [1]
  2348.           write_str = ''
  2349.           if poschar '0-9A-F' hexchar then
  2350.             if hexchar >= 'A' then
  2351.               hexchar = (bin2int hexchar) - 55
  2352.             end
  2353.             fullchar = bin2int (getchar)
  2354.             if windowflag '2?' then
  2355.               ovltext (char hexchar | (fullchar & 0xf0))
  2356.               right
  2357.             else
  2358.               writetext (char (hexchar shl 4) | (if? (insert?) 0 (fullchar & 0x0f)))
  2359.               left
  2360.               windowflag '+2'
  2361.               keycode = getkey
  2362.               if keycode <> <left> then
  2363.                 keyname = geteventname keycode
  2364.                 if length keyname == 3 then
  2365.                   write_str = keyname [2]
  2366.                 else
  2367.                   queuekey keycode
  2368.                 end
  2369.               end
  2370.             end
  2371.           end
  2372.         end
  2373.         windowflag '-2'
  2374.         undoend
  2375.         return
  2376.       end
  2377.     end
  2378.  
  2379.     // enter the character or string at the cursor and
  2380.     // advance the cursor
  2381.     writetext write_str
  2382.  
  2383.     // get the current window settings
  2384.     setting_str = getsettings
  2385.  
  2386.     // match character
  2387.     if pos 'M' setting_str then
  2388.       instext (case write_str
  2389.                  when '"'  '"'
  2390.                  when '('  ')'
  2391.                  when '['  ']'
  2392.                  when '{'  '}'
  2393.                  otherwise ''
  2394.                end)
  2395.     end
  2396.  
  2397.     // translate
  2398.     if pos 'T' setting_str then
  2399.  
  2400.       // delimited lookup?
  2401.       to_word_end = if? (posnot _TranCSet write_str) 2 1
  2402.  
  2403.       // get the last word typed
  2404.       word_str = getword _TranCSet (getcol - to_word_end)
  2405.       if word_str then
  2406.         lookup_str = word_str + (if? to_word_end == 2 '*')
  2407.  
  2408.         if (object? _TranObj) or
  2409.            (loadobject (bootpath "tran.x") _TranObj) then
  2410.  
  2411.           // lookup the word in the translate object
  2412.           value = lookup lookup_str _TranObj
  2413.  
  2414.           if value then
  2415.             // is it a function? then evaluate it..
  2416.             if function? lookup_str _TranObj then
  2417.               eval value
  2418.  
  2419.             // otherwise replace the word
  2420.             else
  2421.               word_column = getcol - length word_str - to_word_end + 1
  2422.               delchar length word_str word_column
  2423.               instext value word_column
  2424.               col word_column + length value + to_word_end - 1
  2425.             end
  2426.           end
  2427.         end
  2428.       end
  2429.     end
  2430.  
  2431.     // check for word wrap and live wrap
  2432.     if (apparentcol (getlinelen)) > _RMargin then
  2433.  
  2434.       // live word wrap
  2435.       if pos 'L' setting_str then
  2436.         livewrap
  2437.  
  2438.       // standard word wrap
  2439.       elseif (pos 'W' setting_str) and (not fold?) then
  2440.         column = apparentcol (getcol)
  2441.         limit = _RMargin + 1
  2442.         if column > limit then
  2443.           if write_str <> ' ' then
  2444.             first_col = if? (setting? 'A') (apparentcol (getlinebeg)) _LMargin
  2445.             split_col = apparentcol (pos ' ' (gettext 1 (actualcol limit)) 'r')
  2446.             split_col = if? split_col > first_col  split_col + 1  limit
  2447.             splitline (actualcol split_col)
  2448.             down
  2449.             shiftblock  first_col - 1 '*l'
  2450.             col (actualcol column - split_col + first_col)
  2451.           end
  2452.         end
  2453.       end
  2454.     end
  2455.  
  2456.     undoend
  2457.   end
  2458.  
  2459.   // enter a date/time stamp at the cursor
  2460.   function timestamp
  2461.     //write getdate + ' ' + gettime
  2462.     write (runmacro (bootpath "cfg\\cfgintnl.x") '' 'f')
  2463.   end
  2464.  
  2465.  
  2466. //--------------------------------------------------------------------
  2467. // File Manager windows
  2468. //--------------------------------------------------------------------
  2469.  
  2470. object fmgr
  2471.  
  2472.   // error notification
  2473.   function ferror (s)
  2474.     msgbox  s + " Failed"  "Error!" 'b'
  2475.     fbreak
  2476.   end
  2477.  
  2478.   // fmgr confirmation prompt
  2479.   private function fconfirm (confirm pstring func)
  2480.     if (icompare confirm 'n') or
  2481.        (icompare (popup "ok" pstring + ' ' + fname + '?') "ok") then
  2482.       fcommand func
  2483.     end
  2484.   end
  2485.  
  2486.   // run external fmgr commands
  2487.   private function frunmacro (file p1 p2)
  2488.     runmacro (bootpath "macro\\" + file + ".x") '' p1 p2
  2489.   end
  2490.  
  2491.   // insert a new file into the list
  2492.   function finsert (file)
  2493.     insline
  2494.     down
  2495.     fupdate file
  2496.     up
  2497.   end
  2498.  
  2499.   // return reduced file name for fmgr commands
  2500.   function fname
  2501.     if fmark? then
  2502.       "Marked Files and Directories"
  2503.     else
  2504.       file = fgetfile
  2505.       if file [LAST_CHAR] == '\\' then
  2506.         (getname file [1..length file - 1]) + '\\'
  2507.       else
  2508.         getname file
  2509.       end
  2510.     end
  2511.   end
  2512.  
  2513.   // internal fopen
  2514.   function fopen2 (file options)
  2515.     if file then
  2516.       open file options
  2517.     else
  2518.       fcommand "fopen2" options
  2519.     end
  2520.   end
  2521.  
  2522.   // fmgr open file(s) command
  2523.   function fopen (options)
  2524.  
  2525.     fmgrwin = getcurrwin
  2526.     fopt = fgetopt
  2527.  
  2528.     // force one file/directory only
  2529.     if pos '1' options then
  2530.       if shiftkey? then
  2531.         options = options + 'v'
  2532.       end
  2533.       file = fgetfile
  2534.       if file [LAST_CHAR] == '\\' then
  2535.         options = options + 'r'
  2536.       end
  2537.       open file options
  2538.  
  2539.     // one or more files/directories
  2540.     else
  2541.       fopen2 '' options
  2542.     end
  2543.  
  2544.     if not (pos 'r' options) and
  2545.        (_FmgrQuit == 'y' or (pos 'q' options)) then
  2546.       // do not quit fully-qualified listings
  2547.       if not pos 'q' fopt then
  2548.         if gotowindow fmgrwin then
  2549.           if gotobuf (getwinbuf) then
  2550.             fmgr.close
  2551.           end
  2552.         end
  2553.       end
  2554.     end
  2555.   end
  2556.  
  2557.   // fmgr run file/macro command (one file only)
  2558.   function frun (options)
  2559.     file = fgetfile
  2560.     if (locase (getext file)) == '.x' then
  2561.       runmacro2 file
  2562.     else
  2563.       run file options
  2564.     end
  2565.   end
  2566.  
  2567.   // fmgr print file(s) command
  2568.   function fprint (file)
  2569.     if file then
  2570.       if not printfile file then
  2571.         ferror "Print"
  2572.       end
  2573.     else
  2574.       fconfirm 'y' "Print" "fprint"
  2575.     end
  2576.   end
  2577.  
  2578.   // fmgr remove file(s) from list
  2579.   function fremove (file)
  2580.     if file then
  2581.       delline
  2582.     else
  2583.       fcommand "fremove"
  2584.     end
  2585.   end
  2586.  
  2587.   // fmgr get file/directory statistics (one file only)
  2588.   function fstat
  2589.     runmacro (bootpath "macro\\filestat.x") '' (fgetfile)
  2590.   end
  2591.  
  2592.   // fmgr touch file(s) command
  2593.   function ftouch (file)
  2594.     if file then
  2595.       if touchfile file then
  2596.         fupdate file
  2597.       else
  2598.         ferror "Touch"
  2599.       end
  2600.     else
  2601.       fconfirm _ConTch "Touch" "ftouch"
  2602.     end
  2603.   end
  2604.  
  2605.   // fmgr change attributes command
  2606.   function fattr  frunmacro "fattr"
  2607.  
  2608.   // fmgr rename file command (one file only)
  2609.   function frename
  2610.     file = fgetfile
  2611.     if file [LAST_CHAR] == '\\' then
  2612.       file [LAST_CHAR] = ''
  2613.       d = '\\'
  2614.     end
  2615.     newname = ask "Rename " + (getname file) + d + " to"  "_load"
  2616.     if newname then
  2617.       newname = qualify newname (getbufname)
  2618.       if renamefile file newname then
  2619.         fupdate newname
  2620.       else
  2621.         ferror "Rename"
  2622.       end
  2623.     end
  2624.   end
  2625.  
  2626.   // fmgr delete file(s) command
  2627.   function fdelete (file)
  2628.     if file then
  2629.       // delete directory
  2630.       if file [LAST_CHAR] == '\\' then
  2631.         if pos ".." file then
  2632.           return
  2633.         else
  2634.           display
  2635.           //queue "onalarm"
  2636.           if (okbox "Deleting: " + (onname file 't') +
  2637.                     "\nCAUTION!! All files and subdirectories will be deleted. Proceed?"
  2638.                    "Warning!") == 'Ok' then
  2639.             success = runmacro (bootpath "macro\\sweep.x") '' file '' 'd'
  2640.           else
  2641.             return
  2642.           end
  2643.         end
  2644.       else
  2645.         success = deletefile file
  2646.       end
  2647.       if success then
  2648.         delline
  2649.       else
  2650.         ferror "Delete"
  2651.       end
  2652.     else
  2653.       file = fgetfile
  2654.       if not (pos ".." file) or fmark? then
  2655.         fconfirm (if? (not fmark? and (directory? file)) 'n' _ConDel)
  2656.                   "Delete" "fdelete"
  2657.       end
  2658.     end
  2659.   end
  2660.  
  2661.   // copy/move files/directories
  2662.   function fcopy  frunmacro "fcopy"
  2663.   function fmove  frunmacro "fcopy" 'm'
  2664.  
  2665.   // open/replace a file list
  2666.   function flopen (file options)  frunmacro "flopen" file options
  2667.  
  2668.   // save/edit a file list
  2669.   function flsave (options) frunmacro "flsave" options
  2670.  
  2671.   // fmgr create new directory command
  2672.   function fmkdir
  2673.     dir = ask "New directory name" "_load"
  2674.     if dir then
  2675.       dir = qualify dir (getbufname)
  2676.       if createdir dir then
  2677.         if (getpath dir) == (getpath (getbufname)) then
  2678.           finsert dir
  2679.         end
  2680.       else
  2681.         ferror "Create directory"
  2682.       end
  2683.     end
  2684.   end
  2685.  
  2686. //--------------------------------------------------------------------
  2687. // Event functions called by the editor
  2688. //--------------------------------------------------------------------
  2689.  
  2690. // edit windows & file manager windows only
  2691. object edit_fmgr
  2692.  
  2693.   // called while loading files
  2694.   event <loading> (file lines)
  2695.     say (if? lines  "Loading [" + lines + "]..."  gettitle)
  2696.   end
  2697.  
  2698.   // called while saving files
  2699.   event <saving> (file lines)
  2700.     say (if? lines  "Saving [" + lines + "]..."  gettitle)
  2701.   end
  2702.  
  2703.   // called while printing files
  2704.   event <printing> (file lines)
  2705.     say (if? lines  "Printing [" + lines + "]... <ctrl break> to stop "
  2706.          gettitle)
  2707.   end
  2708.  
  2709.   // called while compiling files
  2710.   event <compiling> (file lines)
  2711.     say (if? lines  "Compiling " + (onname file) + " [" + lines + "]..."
  2712.                      gettitle)
  2713.   end
  2714.  
  2715. // edit windows only
  2716. object edit
  2717.  
  2718.   // called after a file is opened and before it's displayed
  2719.   function onopen (options)
  2720.  
  2721.     // set window event object
  2722.     setwinobj "edit"
  2723.     foldoptions 'l'
  2724.  
  2725.     // default window settings (if not remembered by open)
  2726.     if not getsettings then
  2727.       setting _DefaultSet ON
  2728.     end
  2729.  
  2730.     // real tabs
  2731.     if not getbinarylen then
  2732.       // handle option to display tabs as spaces, if found on open
  2733.       // (check only last 200 lines in the file)
  2734.       if pos 'o' _TabOpt then
  2735.         oldmark = usemark 'T'
  2736.         markline getlines - 200 (getlines)
  2737.         found = find "\t" "bgn*"
  2738.         destroymark
  2739.         usemark oldmark
  2740.         setbuftabs (if? found _TabWidth)
  2741.       // always display tabs as spaces, without checking
  2742.       elseif pos 's' _TabOpt then
  2743.         setbuftabs _TabWidth
  2744.       end
  2745.     end
  2746.  
  2747.     // hex open option
  2748.     if pos 'x' options then
  2749.       setting 'H' ON
  2750.     end
  2751.  
  2752.     // check for file truncation
  2753.     if bufferflag 't?' then
  2754.       display
  2755.       say "File Truncated!" 'b'
  2756.     end
  2757.  
  2758.     pass options
  2759.   end
  2760.  
  2761.   // called immediately before a file is saved
  2762.   //function onsave (file)
  2763.     //pass file
  2764.   //end
  2765.  
  2766.   // called when switching to a file or window
  2767.   //function onfocus
  2768.     //pass
  2769.   //end
  2770.  
  2771.   // called when closing a file
  2772.   //function onclose
  2773.     //pass
  2774.   //end
  2775.  
  2776.   // called after a search to change the window view and
  2777.   // optionally highlight a string
  2778.   function onfound (stringlength)
  2779.  
  2780.     // check if the cursor is outside the window view
  2781.     x = apparentcol (getcol)
  2782.     if x < getviewcols then
  2783.       adjustcol x
  2784.     elseif x < getviewleft then
  2785.       if x < getviewcols then
  2786.         rollcol -getviewleft
  2787.       else
  2788.         adjustcol 3
  2789.       end
  2790.     elseif x + stringlength >= getviewright then
  2791.       adjustcol
  2792.     end
  2793.  
  2794.     if getrow > getviewbot then
  2795.       adjustrow 3
  2796.     elseif getrow < getviewtop then
  2797.       adjustrow
  2798.     end
  2799.     display
  2800.  
  2801.     // highlight a string if stringlength is specified
  2802.     if stringlength then
  2803.       hilite stringlength 1 (getpalette (if? (inmark?) 9 8))
  2804.     end
  2805.   end
  2806.  
  2807.  
  2808. // file Manager windows only
  2809. object fmgr
  2810.  
  2811.   // called after a fmgr window is opened and before it's displayed
  2812.   function onopen (options)
  2813.     // set the window event object
  2814.     setwinobj "fmgr"
  2815.     pass options
  2816.   end
  2817.  
  2818.  
  2819. // all windows
  2820. object a
  2821.  
  2822.   // called when sounding an alarm (customizable alarm sound)
  2823.   function onalarm
  2824.     beep 750 70
  2825.   end
  2826.  
  2827.   // get default comments for a filename (c1, c2 passed by reference)
  2828.   // (associates a filename with comment symbols)
  2829.   function oncomment (file c1 c2)
  2830.     case locase (getext file)
  2831.       when ".c", ".aml", ".cpp", ".h"   c1 = "//"
  2832.       when ".asm"                       c1 = ';'
  2833.       when ".pas"                       c1 = '{'   c2 = '}'
  2834.       otherwise                         c1 = '>'
  2835.     end
  2836.   end
  2837.  
  2838.   // get a formatted filespec
  2839.   // (note: this function is not called for each file in a file manager
  2840.   // listing when the listing is initially opened)
  2841.   function onname (file options)
  2842.     case _NameStyle
  2843.       // capitalize
  2844.       when 'c'
  2845.         file = locase file
  2846.         file [1] = upcase file [1]
  2847.         i = 1
  2848.         loop
  2849.           j = pos '\\' file [i..TO_END]
  2850.           if j then
  2851.             i = i + j
  2852.             file [i] = upcase file [i]
  2853.           else
  2854.             return file
  2855.           end
  2856.         end
  2857.       // lowercase
  2858.       when 'l'
  2859.         locase file
  2860.       // uppercase
  2861.       when 'u'
  2862.         upcase file
  2863.       // as-is
  2864.       otherwise
  2865.         file
  2866.     end
  2867.   end
  2868.  
  2869.   // called when entering the editor before any windows are open.
  2870.   // Dos command-line parameters are passed to this function
  2871.   function onentry
  2872.  
  2873.     // save the Dos entry path
  2874.     _cp = getcurrpath
  2875.  
  2876.     // open prompt and window history
  2877.     if _SaveHistory == 'y' then
  2878.       openhistory (bootpath "default.prj")
  2879.     end
  2880.  
  2881.     // process command-line parameters passed to the editor
  2882.     param_num = 1
  2883.     parameter = arg 1
  2884.     while parameter do
  2885.  
  2886.       // check for command-line events
  2887.       if parameter [1..2] == "-e"  then
  2888.         send parameter [3 : TO_END]
  2889.  
  2890.       // check for command-line external macros
  2891.       elseif parameter [1..2] == "-r"  then
  2892.         send "runmacro2" parameter [3 : TO_END]
  2893.  
  2894.       // open files/directories
  2895.       else
  2896.         open parameter
  2897.       end
  2898.  
  2899.       // next command line parm
  2900.       param_num = param_num + 1
  2901.       parameter = arg param_num
  2902.     end
  2903.  
  2904.     window = getcurrwin
  2905.     while window and not (wintype? "edit_fmgr" window) do
  2906.       window = getprevwin
  2907.     end
  2908.  
  2909.     // do bootoptions if no edit/fmgr windows are open
  2910.     if not window then
  2911.       case _BootOpt
  2912.         when 'd'  restoredesk
  2913.         when 'f'  open '.'
  2914.         when 'n'  opennew
  2915.         when 't'  runmacro2 "tree"
  2916.         otherwise
  2917.           filespec = ask "File or Directory" "_load"
  2918.           if filespec then
  2919.             open filespec
  2920.           else
  2921.             halt
  2922.           end
  2923.       end
  2924.     end
  2925.  
  2926.     // initialize the mouse
  2927.     if _Mouse == 'y' then
  2928.       if openmouse _MouseOpt then
  2929.         mousepos  15999 + getvidcols  15999 + getvidrows
  2930.         y_sens = _MouSenY
  2931.         if (getos 'v') > 9 then
  2932.           mousesense (_MouSenX * 5) / 8  (y_sens * 5) / 8  _MouDST
  2933.         else
  2934.           mousesense _MouSenX y_sens _MouDST
  2935.         end
  2936.       end
  2937.     end
  2938.  
  2939.     // open key macros if configured
  2940.     if _SaveMac == 'y' then
  2941.       openkey (bootpath "a.mac")
  2942.     end
  2943.  
  2944.     // set autosave timer
  2945.     send "autosave" _AutoSave
  2946.   end
  2947.  
  2948.  
  2949.   // called when exiting the editor after all windows are closed
  2950.   function onexit
  2951.  
  2952.     // open prompt on non-global exit (if configured)
  2953.     if not __G then
  2954.       if _ExitOpen == 'y' then
  2955.         filespec = ask "File or Directory" "_load"
  2956.         if filespec then
  2957.           open filespec
  2958.         end
  2959.       end
  2960.     end
  2961.  
  2962.     // final exit if no windows open
  2963.     if not getcurrwin then
  2964.  
  2965.       // save prompt and window history
  2966.       if _SaveHistory == 'y' then
  2967.         savehistory (bootpath "default.prj")
  2968.       end
  2969.  
  2970.       // save key macros if configured
  2971.       if _SaveMac == 'y' then
  2972.         // check if record occurred
  2973.         if lookup "kd" "mon" then
  2974.           savekey (bootpath "a.mac")
  2975.         end
  2976.       end
  2977.  
  2978.       // restore entry path saved in onentry
  2979.       currpath _cp
  2980.  
  2981.       closemouse
  2982.       halt
  2983.     end
  2984.   end
  2985.